package junit.awtui; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Checkbox; import java.awt.Color; import java.awt.Component; import java.awt.FlowLayout; import java.awt.Font; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Image; import java.awt.Insets; import java.awt.Label; import java.awt.List; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.Panel; import java.awt.SystemColor; import java.awt.TextArea; import java.awt.TextField; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.TextEvent; import java.awt.event.TextListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.ImageProducer; import java.lang.reflect.Constructor; import java.util.Vector; import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestResult; import junit.runner.BaseTestRunner; /** * An AWT based user interface to run tests. * Enter the name of a class which either provides a static * suite method or is a subclass of TestCase. * <pre> * Synopsis: java junit.awtui.TestRunner [-noloading] [TestCase] * </pre> * TestRunner takes as an optional argument the name of the testcase class to be run. */ public class TestRunner extends BaseTestRunner { protected Frame fFrame; protected Vector fExceptions; protected Vector fFailedTests; protected Thread fRunner; protected TestResult fTestResult; protected TextArea fTraceArea; protected TextField fSuiteField; protected Button fRun; protected ProgressBar fProgressIndicator; protected List fFailureList; protected Logo fLogo; protected Label fNumberOfErrors; protected Label fNumberOfFailures; protected Label fNumberOfRuns; protected Button fQuitButton; protected Button fRerunButton; protected TextField fStatusLine; protected Checkbox fUseLoadingRunner; protected static Font PLAIN_FONT= new Font("dialog", Font.PLAIN, 12); private static final int GAP= 4; public TestRunner() { } private void about() { AboutDialog about= new AboutDialog(fFrame); about.setModal(true); about.setLocation(300, 300); about.setVisible(true); } public void addError(Test test, Throwable t) { fNumberOfErrors.setText(Integer.toString(fTestResult.errorCount())); appendFailure("Error", test, t); } public void addFailure(Test test, AssertionFailedError t) { fNumberOfFailures.setText(Integer.toString(fTestResult.failureCount())); appendFailure("Failure", test, t); } protected void addGrid(Panel p, Component co, int x, int y, int w, int fill, double wx, int anchor) { GridBagConstraints c= new GridBagConstraints(); c.gridx= x; c.gridy= y; c.gridwidth= w; c.anchor= anchor; c.weightx= wx; c.fill= fill; if (fill == GridBagConstraints.BOTH || fill == GridBagConstraints.VERTICAL) c.weighty= 1.0; c.insets= new Insets(y == 0 ? GAP : 0, x == 0 ? GAP : 0, GAP, GAP); p.add(co, c); } private void appendFailure(String kind, Test test, Throwable t) { kind+= ": " + test; String msg= t.getMessage(); if (msg != null) { kind+= ":" + truncate(msg); } fFailureList.add(kind); fExceptions.addElement(t); fFailedTests.addElement(test); if (fFailureList.getItemCount() == 1) { fFailureList.select(0); failureSelected(); } } /** * Creates the JUnit menu. Clients override this * method to add additional menu items. */ protected Menu createJUnitMenu() { Menu menu= new Menu("JUnit"); MenuItem mi= new MenuItem("About..."); mi.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { about(); } } ); menu.add(mi); menu.addSeparator(); mi= new MenuItem("Exit"); mi.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent event) { System.exit(0); } } ); menu.add(mi); return menu; } protected void createMenus(MenuBar mb) { mb.add(createJUnitMenu()); } protected TestResult createTestResult() { return new TestResult(); } protected Frame createUI(String suiteName) { Frame frame= new Frame("JUnit"); Image icon= loadFrameIcon(); if (icon != null) frame.setIconImage(icon); frame.setLayout(new BorderLayout(0, 0)); frame.setBackground(SystemColor.control); final Frame finalFrame= frame; frame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { finalFrame.dispose(); System.exit(0); } } ); MenuBar mb = new MenuBar(); createMenus(mb); frame.setMenuBar(mb); //---- first section Label suiteLabel= new Label("Test class name:"); fSuiteField= new TextField(suiteName != null ? suiteName : ""); fSuiteField.selectAll(); fSuiteField.requestFocus(); fSuiteField.setFont(PLAIN_FONT); fSuiteField.setColumns(40); fSuiteField.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { runSuite(); } } ); fSuiteField.addTextListener( new TextListener() { public void textValueChanged(TextEvent e) { fRun.setEnabled(fSuiteField.getText().length() > 0); fStatusLine.setText(""); } } ); fRun= new Button("Run"); fRun.setEnabled(false); fRun.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { runSuite(); } } ); boolean useLoader= useReloadingTestSuiteLoader(); fUseLoadingRunner= new Checkbox("Reload classes every run", useLoader); if (inVAJava()) fUseLoadingRunner.setVisible(false); //---- second section fProgressIndicator= new ProgressBar(); //---- third section fNumberOfErrors= new Label("0000", Label.RIGHT); fNumberOfErrors.setText("0"); fNumberOfErrors.setFont(PLAIN_FONT); fNumberOfFailures= new Label("0000", Label.RIGHT); fNumberOfFailures.setText("0"); fNumberOfFailures.setFont(PLAIN_FONT); fNumberOfRuns= new Label("0000", Label.RIGHT); fNumberOfRuns.setText("0"); fNumberOfRuns.setFont(PLAIN_FONT); Panel numbersPanel= new Panel(new FlowLayout()); numbersPanel.add(new Label("Runs:")); numbersPanel.add(fNumberOfRuns); numbersPanel.add(new Label(" Errors:")); numbersPanel.add(fNumberOfErrors); numbersPanel.add(new Label(" Failures:")); numbersPanel.add(fNumberOfFailures); //---- fourth section Label failureLabel= new Label("Errors and Failures:"); fFailureList= new List(5); fFailureList.addItemListener( new ItemListener() { public void itemStateChanged(ItemEvent e) { failureSelected(); } } ); fRerunButton= new Button("Run"); fRerunButton.setEnabled(false); fRerunButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { rerun(); } } ); Panel failedPanel= new Panel(new GridLayout(0, 1, 0, 2)); failedPanel.add(fRerunButton); fTraceArea= new TextArea(); fTraceArea.setRows(5); fTraceArea.setColumns(60); //---- fifth section fStatusLine= new TextField(); fStatusLine.setFont(PLAIN_FONT); fStatusLine.setEditable(false); fStatusLine.setForeground(Color.red); fQuitButton= new Button("Exit"); fQuitButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } } ); // --------- fLogo= new Logo(); //---- overall layout Panel panel= new Panel(new GridBagLayout()); addGrid(panel, suiteLabel, 0, 0, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); addGrid(panel, fSuiteField, 0, 1, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); addGrid(panel, fRun, 2, 1, 1, GridBagConstraints.HORIZONTAL, 0.0, GridBagConstraints.CENTER); addGrid(panel, fUseLoadingRunner, 0, 2, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); addGrid(panel, fProgressIndicator, 0, 3, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); addGrid(panel, fLogo, 2, 3, 1, GridBagConstraints.NONE, 0.0, GridBagConstraints.NORTH); addGrid(panel, numbersPanel, 0, 4, 2, GridBagConstraints.NONE, 0.0, GridBagConstraints.CENTER); addGrid(panel, failureLabel, 0, 5, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.WEST); addGrid(panel, fFailureList, 0, 6, 2, GridBagConstraints.BOTH, 1.0, GridBagConstraints.WEST); addGrid(panel, failedPanel, 2, 6, 1, GridBagConstraints.HORIZONTAL, 0.0, GridBagConstraints.CENTER); addGrid(panel, fTraceArea, 0, 7, 2, GridBagConstraints.BOTH, 1.0, GridBagConstraints.WEST); addGrid(panel, fStatusLine, 0, 8, 2, GridBagConstraints.HORIZONTAL, 1.0, GridBagConstraints.CENTER); addGrid(panel, fQuitButton, 2, 8, 1, GridBagConstraints.HORIZONTAL, 0.0, GridBagConstraints.CENTER); frame.add(panel, BorderLayout.CENTER); frame.pack(); return frame; } public void failureSelected() { fRerunButton.setEnabled(isErrorSelected()); showErrorTrace(); } public void endTest(Test test) { setLabelValue(fNumberOfRuns, fTestResult.runCount()); synchronized(this) { fProgressIndicator.step(fTestResult.wasSuccessful()); } } private boolean isErrorSelected() { return fFailureList.getSelectedIndex() != -1; } private Image loadFrameIcon() { Toolkit toolkit= Toolkit.getDefaultToolkit(); try { java.net.URL url= BaseTestRunner.class.getResource("smalllogo.gif"); return toolkit.createImage((ImageProducer) url.getContent()); } catch (Exception ex) { } return null; } public Thread getRunner() { return fRunner; } public static void main(String[] args) { new TestRunner().start(args); } public static void run(Class test) { String args[]= { test.getName() }; main(args); } public void rerun() { int index= fFailureList.getSelectedIndex(); if (index == -1) return; Test test= (Test)fFailedTests.elementAt(index); if (!(test instanceof TestCase)) { showInfo("Could not reload "+ test.toString()); return; } Test reloadedTest= null; try { Class reloadedTestClass= getLoader().reload(test.getClass()); Class[] classArgs= { String.class }; Constructor constructor= reloadedTestClass.getConstructor(classArgs); Object[] args= new Object[]{((TestCase)test).getName()}; reloadedTest=(Test)constructor.newInstance(args); } catch(Exception e) { showInfo("Could not reload "+ test.toString()); return; } TestResult result= new TestResult(); reloadedTest.run(result); String message= reloadedTest.toString(); if(result.wasSuccessful()) showInfo(message+" was successful"); else if (result.errorCount() == 1) showStatus(message+" had an error"); else showStatus(message+" had a failure"); } protected void reset() { setLabelValue(fNumberOfErrors, 0); setLabelValue(fNumberOfFailures, 0); setLabelValue(fNumberOfRuns, 0); fProgressIndicator.reset(); fRerunButton.setEnabled(false); fFailureList.removeAll(); fExceptions= new Vector(10); fFailedTests= new Vector(10); fTraceArea.setText(""); } /** * runs a suite. * @deprecated use runSuite() instead */ public void run() { runSuite(); } protected void runFailed(String message) { showStatus(message); fRun.setLabel("Run"); fRunner= null; } synchronized public void runSuite() { if (fRunner != null) { fTestResult.stop(); } else { setLoading(shouldReload()); fRun.setLabel("Stop"); showInfo("Initializing..."); reset(); showInfo("Load Test Case..."); final Test testSuite= getTest(fSuiteField.getText()); if (testSuite != null) { fRunner= new Thread() { public void run() { fTestResult= createTestResult(); fTestResult.addListener(TestRunner.this); fProgressIndicator.start(testSuite.countTestCases()); showInfo("Running..."); long startTime= System.currentTimeMillis(); testSuite.run(fTestResult); if (fTestResult.shouldStop()) { showStatus("Stopped"); } else { long endTime= System.currentTimeMillis(); long runTime= endTime-startTime; showInfo("Finished: " + elapsedTimeAsString(runTime) + " seconds"); } fTestResult= null; fRun.setLabel("Run"); fRunner= null; System.gc(); } }; fRunner.start(); } } } private boolean shouldReload() { return !inVAJava() && fUseLoadingRunner.getState(); } private void setLabelValue(Label label, int value) { label.setText(Integer.toString(value)); label.invalidate(); label.getParent().validate(); } public void setSuiteName(String suite) { fSuiteField.setText(suite); } private void showErrorTrace() { int index= fFailureList.getSelectedIndex(); if (index == -1) return; Throwable t= (Throwable) fExceptions.elementAt(index); fTraceArea.setText(getFilteredTrace(t)); } private void showInfo(String message) { fStatusLine.setFont(PLAIN_FONT); fStatusLine.setForeground(Color.black); fStatusLine.setText(message); } protected void clearStatus() { showStatus(""); } private void showStatus(String status) { fStatusLine.setFont(PLAIN_FONT); fStatusLine.setForeground(Color.red); fStatusLine.setText(status); } /** * Starts the TestRunner */ public void start(String[] args) { String suiteName= processArguments(args); fFrame= createUI(suiteName); fFrame.setLocation(200, 200); fFrame.setVisible(true); if (suiteName != null) { setSuiteName(suiteName); runSuite(); } } public void startTest(Test test) { showInfo("Running: "+test); } }